<?php
class Lib_Strmethod{
    //1个汉字两个字符
    static function idEncode($id){
        return trim(base64_encode('ctsohu,'.$id),"=");
    }
    //
    static function idDecode($id){
        $id=explode(',',base64_decode($id));
        $id=isset($id[1])?$id[1]:null;;
        return $id;
    }
    static function splitStr($str,$len)
    {
        if($len<=0)
        {
            return false;
        }
        else
        {
            $sLen=strlen($str);
            if($len>=$sLen)
            return $str;
            else
            {
                for($i=0;$i<($len-1);$i++)
                {
                    if(ord(substr($str,$i,1))>0xa0)
                    $i++;
                }
                if($i>=$len)
                return substr($str,0,$len);
                elseif(ord(substr($str,$i,1))>0xa0)
                return substr($str,0,$len-1);
                else
                return substr($str,0,$len);
            }
        }
    }
    static function sub_str_utf8($str,$len){
        $str = @iconv('utf-8','gb2312',$str);
        $str = self::splitStr($str,$len);
        return $str = @iconv('gb2312','utf-8',$str);
    }



    //截取中文字符串
    function mysubstr($str, $start, $len) {
        $tmpstr = "";
        $strlen = $start + $len;
        for($i = 0; $i < $strlen; $i++) {
            if(ord(substr($str, $i, 1)) > 0xa0) {
                $tmpstr .= substr($str, $i, 2);
                $i++;
            } else
            $tmpstr .= substr($str, $i, 1);
        }
        return $tmpstr;
    }

    /**
  * 生成摘要 
  * @param (string) $body  正文 
  * @param (int) $size  摘要长度 
  */ 

    function blog_summary($body, $size){
        $_size = mb_strlen($body, 'utf-8');
        if($_size <= $size) return $body;
        $strlen_var = strlen($body);
        // 不包含 html 标签
        if(strpos($body, '<') === false){
            return mb_substr($body, 0, $size);
        }
        // 包含截断标志，优先
        if($e = strpos($body, '<!-- break -->')){
            return mb_substr($body, 0, $e);
        }
        // html 代码标记
        $html_tag = 0;
        // 摘要字符串
        $summary_string = '';
        /**
    * 数组用作记录摘要范围内出现的 html 标签 
    * 开始和结束分别保存在 left 和 right 键名下 
    * 如字符串为：<h3><p><b>a</b></h3>，假设 p 未闭合 
    * 数组则为：array('left' => array('h3', 'p', 'b'), 'right' => 'b', 'h3'); 
    * 仅补全 html 标签，<? <% 等其它语言标记，会产生不可预知结果 
    */ 
        $html_array = array('left' => array(), 'right' => array());
        for($i = 0; $i < $strlen_var; ++$i) {
            if(!$size){
                break;
            }
            $current_var = substr($body, $i, 1);
            if($current_var == '<'){
                // html 代码开始
                $html_tag = 1;
                $html_array_str = '';
            }else if($html_tag == 1){
                // 一段 html 代码结束
                if($current_var == '>'){
                    /**
          * 去除首尾空格，如 <br /  > < img src="" / > 等可能出现首尾空格 
          */ 
                    $html_array_str = trim($html_array_str);
                    /**
          * 判断最后一个字符是否为 /，若是，则标签已闭合，不记录 
          */ 
                    if(substr($html_array_str, -1) != '/'){
                        // 判断第一个字符是否 /，若是，则放在 right 单元
                        $f = substr($html_array_str, 0, 1);
                        if($f == '/'){
                            // 去掉 /
                            $html_array['right'][] = str_replace('/', '', $html_array_str);
                        }else if($f != '?'){
                            // 判断是否为 ?，若是，则为 PHP 代码，跳过
                            /**
              * 判断是否有半角空格，若有，以空格分割，第一个单元为 html 标签 
              * 如 <h2 class="a"> <p class="a"> 
              */ 
                            if(strpos($html_array_str, ' ') !== false){
                                // 分割成2个单元，可能有多个空格，如：<h2 class="" id="">
                                $html_array['left'][] = strtolower(current(explode(' ', $html_array_str, 2)));
                            }else{
                                /**
                * * 若没有空格，整个字符串为 html 标签，如：<b> <p> 等 
                * 统一转换为小写 
                */ 
                                $html_array['left'][] = strtolower($html_array_str);
                            }
                        }
                    }
                    // 字符串重置
                    $html_array_str = '';
                    $html_tag = 0;
                }else{
                    /**
          * 将< >之间的字符组成一个字符串 
          * 用于提取 html 标签 
          */ 
                    $html_array_str .= $current_var;
                }
            }else{
                // 非 html 代码才记数
                --$size;
            }
            $ord_var_c = ord($body{$i});
            switch (true) {
                case (($ord_var_c & 0xE0) == 0xC0):
                    // 2 字节
                    $summary_string .= substr($body, $i, 2);
                    $i += 1;
                    break;
                case (($ord_var_c & 0xF0) == 0xE0):
                    // 3 字节
                    $summary_string .= substr($body, $i, 3);
                    $i += 2;
                    break;
                case (($ord_var_c & 0xF8) == 0xF0):
                    // 4 字节
                    $summary_string .= substr($body, $i, 4);
                    $i += 3;
                    break;
                case (($ord_var_c & 0xFC) == 0xF8):
                    // 5 字节
                    $summary_string .= substr($body, $i, 5);
                    $i += 4;
                    break;
                case (($ord_var_c & 0xFE) == 0xFC):
                    // 6 字节
                    $summary_string .= substr($body, $i, 6);
                    $i += 5;
                    break;
                default:
                    // 1 字节
                    $summary_string .= $current_var;
            }
        }
        if($html_array['left']){
            /**
      * 比对左右 html 标签，不足则补全 
      */ 
            /**
      * 交换 left 顺序，补充的顺序应与 html 出现的顺序相反 
      * 如待补全的字符串为：<h2>abc<b>abc<p>abc 
      * 补充顺序应为：</p></b></h2> 
      */ 
            $html_array['left'] = array_reverse($html_array['left']);
            foreach($html_array['left'] as $index => $tag){
                // 判断该标签是否出现在 right 中
                $key = array_search($tag, $html_array['right']);
                if($key !== false){
                    // 出现，从 right 中删除该单元
                    unset($html_array['right'][$key]);
                }else{
                    // 没有出现，需要补全
                    $summary_string .= '</'.$tag.'>';
                }
            }
        }
        return $summary_string;
    }

    function closeTags($html) {
        // 不需要补全的标签
        $arr_single_tags = array('meta','img','br','link','area');
        // 匹配开始标签
        preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU',$html,$result);
        $openedtags = $result[1];
        // 匹配关闭标签
        preg_match_all('#</([a-z]+)>#iU',$html,$result);
        $closedtags = $result[1];
        // 计算关闭开启标签数量，如果相同就返回html数据
        $len_opened = count($openedtags);
        if (count($closedtags) == $len_opened){
            return $html;
        }
        // 把排序数组，将最后一个开启的标签放在最前面
        $openedtags = array_reverse($openedtags);
        // 遍历开启标签数组
        for($i=0; $i<$len_opened; $i++){
            // 如果标签不属于需要不全的标签
            if(!in_array($openedtags[$i],$arr_single_tags)){
                // 如果这个标签不在关闭的标签中
                if(!in_array($openedtags[$i],$closedtags)){
                    // 如果在这个标签之后还有开启的标签
                    if(isset($openedtag[$i+1]) && $next_tag = $openedtags[$i+1]){
                        // 将当前的标签放在下一个标签的关闭标签的前面
                        $html = preg_replace('#</'.$next_tag.'#iU','</'.$openedtags[$i].'></'.$next_tag,$html);
                    }else{
                        // 直接补全闭合标签
                        $html .= '</'.$openedtags[$i].'>';
                    }
                }
            }
        }
        return $html;
    }

    function is_utf8($str)
    {
        if (preg_match("/^([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}/",$str) == true || preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){1}$/",$str) == true || preg_match("/([".chr(228)."-".chr(233)."]{1}[".chr(128)."-".chr(191)."]{1}[".chr(128)."-".chr(191)."]{1}){2,}/",$str) == true)
        {
            return true;
        }
        else
        {
            return false;
        }

    }
}
?>
